package com.zzw.springboot.aspect;

import com.zzw.springboot.annotation.RateLimit;
import com.zzw.springboot.util.RedisRateLimiter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 限流注解切面
 */
@Aspect
@Component
public class RateLimitAspect {

    private static final Logger logger = LoggerFactory.getLogger(RateLimitAspect.class);

    @Autowired
    private RedisRateLimiter rateLimiter;

    @Before("@annotation(com.zzw.springboot.annotation.RateLimit)")
    public void doBefore(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        RateLimit rateLimit = method.getAnnotation(RateLimit.class);

        if (rateLimit != null) {
            String key = getLimitKey(rateLimit, method);

            boolean allowed = rateLimiter.isAllowed(key, rateLimit.period(), rateLimit.count());
            if (!allowed) {
                logger.warn("接口访问频率超限: {}", key);
                throw new RuntimeException("请求过于频繁，请稍后再试");
            }
        }
    }

    /**
     * 获取限流键
     */
    private String getLimitKey(RateLimit rateLimit, Method method) {
        String key;
        RateLimit.LimitType limitType = rateLimit.limitType();
        String prefix = rateLimit.prefix();

        switch (limitType) {
            case IP:
                key = prefix + "ip:" + getIpAddress();
                break;
            case USER:
                // 由于未使用Spring Security，这里简单返回"anonymous"
                key = prefix + "user:anonymous";
                break;
            case INTERFACE:
                key = prefix + "interface:" + method.getDeclaringClass().getName() + "." + method.getName();
                break;
            default:
                key = prefix + "unknown";
        }

        return key;
    }

    /**
     * 获取用户ID（简化实现）
     */
    private String getUserId() {
        return "anonymous";
    }

    /**
     * 获取IP地址
     */
    private String getIpAddress() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getHeader("X-Forwarded-For");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return ip;
    }
}
